<template>
  <div class="v-table-td-number-edit">
    <div class="v-table-td-number-edit-tip">
<!--      {{ numFormat(inputNumber) }}-->
      {{ inputNumber }}
    </div>
    <div class="v-table-td-number-edit">
      <input v-model.number="inputNumber" @keydown="onKeyDown" class="v-table-td-number-edit-textarea" ref="textarea" @focus="focus($event)" @blur="onBlur"/>
      <span class="edit-icon" @mousedown.native="showCalculator">
	<svg t="1619668798051" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
       p-id="2232" width="15" height="15" data-spm-anchor-id="a313x.7781069.0.i7"
       xmlns:xlink="http://www.w3.org/1999/xlink"><defs></defs><path
      d="M72 112.197v799.604c0 22.215 17.987 40.198 40.198 40.198h799.604c22.215 0 40.198-17.987 40.198-40.198V112.197c0-22.215-17.987-40.198-40.198-40.198H112.198C89.983 71.999 72 89.986 72 112.197z m220 591.519l-70.613-70.613c-7.652-7.652-20.571-7.907-28.381-0.097-7.583 7.582-7.767 20.517 0.097 28.381L263.716 732l-70.613 70.613c-7.652 7.652-7.907 20.571-0.097 28.381 7.582 7.583 20.517 7.767 28.381-0.097L292 760.284l70.613 70.613c7.652 7.652 20.571 7.907 28.381 0.097 7.582-7.582 7.767-20.517-0.097-28.381L320.284 732l70.613-70.613c7.652-7.652 7.907-20.571 0.097-28.381-7.582-7.582-20.517-7.767-28.381 0.097L292 703.716zM272 272h-99.863C161.316 272 152 280.954 152 292c0 10.722 9.016 20 20.137 20H272v99.863c0 10.821 8.954 20.137 20 20.137 10.723 0 20-9.016 20-20.137V312h99.863c10.821 0 20.137-8.954 20.137-20 0-10.722-9.016-20-20.137-20H312v-99.863c0-10.821-8.954-20.137-20-20.137-10.722 0-20 9.016-20 20.137V272zM32 112.197C32 67.905 67.881 32 112.197 32h799.604c44.292 0 80.197 35.881 80.197 80.197v799.604c0 44.292-35.881 80.197-80.197 80.197H112.197C67.905 991.998 32 956.117 32 911.801V112.197zM552 292c0-11.046 9.316-20 20.137-20h239.726c11.122 0 20.137 9.278 20.137 20 0 11.046-9.316 20-20.137 20H572.137C561.015 312 552 302.722 552 292z m0 360c0-11.046 9.316-20 20.137-20h239.726c11.122 0 20.137 9.278 20.137 20 0 11.046-9.316 20-20.137 20H572.137C561.015 672 552 662.722 552 652z m0 160c0-11.046 9.316-20 20.137-20h239.726c11.122 0 20.137 9.278 20.137 20 0 11.046-9.316 20-20.137 20H572.137C561.015 832 552 822.722 552 812z"
      p-id="2233"></path></svg>
</span>
    </div>
  </div>
  <div v-if="calculateStatus" class="calculator" @mousedown.native="noInputData">
    <div class="result" style="grid-area:result;">
      <span class="result-info">{{ equation }}</span>
    </div>
    <button style="grid-area:ac" @click="clear">C</button>
    <button style="grid-area:plus-minus" @click="calculateToggle">±</button>
    <button style="grid-area:percent" @click="calculatePercentage">%</button>
    <button style="grid-area:add" @click="append('+')">+</button>
    <button style="grid-area:subtract" @click="append('-')">-</button>
    <button style="grid-area:multiply" @click="append('×')">×</button>
    <button style="grid-area:divide" @click="append('÷')">÷</button>
    <button style="grid-area:equal" @click="calculate">=</button>
    <button style="grid-area:number-1" @click="append(1)">1</button>
    <button style="grid-area:number-2" @click="append(2)">2</button>
    <button style="grid-area:number-3" @click="append(3)">3</button>
    <button style="grid-area:number-4" @click="append(4)">4</button>
    <button style="grid-area:number-5" @click="append(5)">5</button>
    <button style="grid-area:number-6" @click="append(6)">6</button>
    <button style="grid-area:number-7" @click="append(7)">7</button>
    <button style="grid-area:number-8" @click="append(8)">8</button>
    <button style="grid-area:number-9" @click="append(9)">9</button>
    <button style="grid-area:number-0" @click="append(0)">0</button>
    <button style="grid-area:dot" @click="append('.')">.</button>
    <button style="grid-area:canceld" @click="cancelData">取消</button>
    <button style="grid-area:enterd" @click="enterData">确定</button>
  </div>
</template>

<script setup>
import {defineEmits, defineProps, h, inject, nextTick, onMounted, ref, watch} from "vue";
import VTableNumberCalculator from "@components/common/VoucherTable/VTableNumberCalculator.vue";
import {layer} from "@layui/layer-vue";
import {isNumber} from "xe-utils";

const emits = defineEmits(['cancelEdit', 'onNext']);

const props = defineProps({
  number: {
    type: [Number, String]
  },
  readonly: {
    type: Boolean,
    default: false
  },
  rowIndex: Number,
  field: String
});


const textarea = ref(null)
const inputNumber = ref(null)

const calculateStatus = ref(false)
const equation = ref('0')
const isDecimalAdded = ref(false)
const isOperatorAdded = ref(false)
const isStarted = ref(false)
const onlyEditStatus = ref(true)

const autoEqAmount = inject('autoEqAmount');
const next = inject('next');

const onKeyDown = (e) => {
  if (['+', '-', '*', '/', '＋', '－', '＊', '／'].includes(e.key)) {
    if (['-', '－'].includes(e.key) && Number(props.number || props.number.value)) {
      showCalculators(e.key);
    }
  } else if (e.key === '-' || e.key === '－') {
    if (inputNumber.value !== null && inputNumber.value !== '') {
      showCalculators(e.key);
    }
  }
  if ((e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode >= 96 && e.keyCode <= 105) || [190, 110].includes(e.keyCode)) {
    //先拼接出下一个输入值
    let numStr = insertStr(e.target.value, getCursorPosition(e.target), e.key);
    let num = Number(numStr);
    //判断是否是数字
    if (typeof num === 'number' && !isNaN(num)) {
      if (numStr.indexOf('.') !== -1) {
        //不能超过两位小数
        if (numStr.split('.')[1].length > 2) {
          e.preventDefault();
        }
      }
      //不能超过最大值
      if (num > 999999999.99) {
        e.preventDefault();
      }
    } else {
      e.preventDefault();
    }
  } else if (e.keyCode === 13 || e.keyCode === 9) {//回车
    emits('onNext', inputNumber.value)
    e.preventDefault();
  } else if (e.key === '=' || e.key === '＝') {//等于
    autoEqAmount(props.rowIndex, props.field);
    e.preventDefault();
  } else if (e.key === '+' || e.key === '＋') {//加
    e.preventDefault();
  } else if (e.key === '-' || e.key === '－') {//减
    if (e.target.value.length) {
      e.preventDefault();
    }
  } else if (e.keyCode === 8) {//删除

  } else if (e.keyCode === 32) {//空格
    next(props.rowIndex, props.field === 'debitAmount' ? 'creditAmount' : 'debitAmount');
  } else if ([37, 39].includes(e.keyCode)) {//左右移动

  } else if ((e.composed || e.ctrlKey) && (['c', 'v', 'ｃ', 'ｖ'].includes(e.key))) {

  } else {
    e.preventDefault();
  }
}

const onBlur = () => {
  if (onlyEditStatus.value) {
    emits('cancelEdit', inputNumber.value)
  } else {
    return false;
  }
}

const focus = (event) => {
  nextTick(() => {
    textarea.value.focus();
    textarea.value.select();
  })
}

const getCursorPosition = (element) => {
  let startPos = element.selectionStart; // 获取光标开始的位置
  let endPos = element.selectionEnd; // 获取光标结束的位置
  if (startPos === undefined || endPos === undefined) return 0; // 如果没有光标位置 不操作
  return {startPos, endPos};
}

const insertStr = (source, pos, newStr) => {
  if (pos.startPos === pos.endPos) {
    return source.slice(0, pos.endPos) + newStr + source.slice(pos.endPos)
  }
  return source.slice(0, pos.startPos) + newStr + source.slice(pos.endPos)
}

const showCalculator = (event) => {
  event.preventDefault();
  if (calculateStatus.value) {
    calculateStatus.value = false
  } else calculateStatus.value = true
  if (inputNumber.value !== '' && inputNumber.value !== null) equation.value = inputNumber.value
}

const showCalculators = (key) => {
  onlyEditStatus.value = false;
  let oData = '';
  if (inputNumber.value === null) {
    oData = key;
  } else {
    oData = inputNumber.value + key
  }
  let layerId = layer.open({
    title: "四则运算",
    shadeClose: false,
    closeBtn: 1,
    area: ['600px', '360px'],
    zIndex: 1000,
    content: h(VTableNumberCalculator, {
      originData: oData,
      onClose: () => {
        layer.close(layerId);
      },
      onSuccess: (resultData) => {
        inputNumber.value = Number(Number(resultData).toFixed(2));
        layer.close(layerId);
      }
    }),
    end: () => {
      onlyEditStatus.value = true;
      nextTick(() => {
        textarea.value.focus();
      })
      layer.close(layerId);
    },
  });
}

//输入+ - x /
const isOperator = (character) => {
  return ["+", "-", "×", "÷"].indexOf(character) > -1;
}

// operators or Numbers
const append = (character) => {
  //首次输入时不为操作符
  if (equation.value === "0" && !isOperator(character)) {
    if (character === ".") {
      equation.value += "" + character; //引号的作用将其转换成字符串
      isDecimalAdded.value = true;
    } else {
      equation.value = "" + character;
    }
    isStarted.value = true;
    return;
  }

  //if NUmber
  if (!isOperator(character)) {
    //防止连续输入.
    if (character === "." && isDecimalAdded.value) {
      return;
    }
    if (character === ".") {
      isDecimalAdded.value = true;
      isOperatorAdded.value = true;
    } else {
      isOperatorAdded.value = false;
    }
    equation.value += "" + character;
  }

  //Add Operator
  if (isOperator(character) && !isOperatorAdded.value) {
    equation.value += "" + character;
    isDecimalAdded.value = false;
    isOperatorAdded.value = true;
  }
}

//=
const calculate = () => {
  if (!isNumber(equation.value)) {
    let result = equation.value
        .replace(new RegExp("undefined", "g"), "")
        .replace(new RegExp("×", "g"), "*")
        .replace(new RegExp("÷", "g"), "/");

    equation.value = parseFloat(eval(result).toFixed(9)).toString();
    isDecimalAdded.value = false;
    isOperatorAdded.value = false;
  }

}

//正负号+/-
const calculateToggle = () => {
  // if (isOperatorAdded.value || !isStarted.value) {
  //     return;
  // }
  // equation.value = equation.value + "* -1";
  // calculate();

  //得到最后一位数值
  let lastNumber = equation.value.substring(equation.value.lastIndexOf(' '))

  //得到之前的数值+符号
  let prevNumber = equation.value.substring(0, equation.value.lastIndexOf(' '))

  //判断当前是否有正负号
  if (lastNumber.indexOf('-') === -1) {
    lastNumber = ' -' + lastNumber.trim()
  } else {
    lastNumber = ' ' + lastNumber.trim().substring(1)
  }

  //合并
  equation.value = prevNumber + lastNumber
}

//%
const calculatePercentage = () => {
  if (isOperatorAdded.value || !isStarted.value) {
    return;
  }
  equation.value = equation.value + "* 0.01";
  calculate();
}

//AC
const clear = () => {
  (equation.value = "0"),
      (isDecimalAdded.value = false),
      (isOperatorAdded.value = false),
      (isStarted.value = false);
}

//取消
const cancelData = () => {
  (equation.value = "0"),
      (isDecimalAdded.value = false),
      (isOperatorAdded.value = false),
      (isStarted.value = false);
  calculateStatus.value = false;
}

//确认
const enterData = () => {
  let result = equation.value
      .replace(new RegExp("undefined", "g"), "")
      .replace(new RegExp("×", "g"), "*")
      .replace(new RegExp("÷", "g"), "/");

  equation.value = parseFloat(eval(result).toFixed(9)).toString();
  isDecimalAdded.value = false;
  isOperatorAdded.value = false;

  if (equation.value === "0") {
    inputNumber.value = ''
  } else {
    inputNumber.value = Number(Number(equation.value).toFixed(2))
  }
  (isDecimalAdded.value = false),
      (isOperatorAdded.value = false),
      (isStarted.value = false);
  nextTick(() => {
    textarea.value.focus();
    textarea.value.select();
  })
  calculateStatus.value = false;
}


// 无效点击
const noInputData = (event) => {
  event.preventDefault();
}


watch(() => props.number, (val) => {
  inputNumber.value = val;
})

onMounted(() => {
  nextTick(() => {
    inputNumber.value = props.number;
    textarea.value.focus();
  })
})
</script>

<style scoped lang="less">
.v-table {

  &-td {
    &-number {
      &-edit {
        height: 100%;
        position: relative;

        &-tip {
          position: absolute;
          height: 60px;
          width: 220px;
          top: -65px;
          background-color: @white-color;
          left: 0;
          font-weight: bold;
          font-size: 26px;
          text-align: right;
          line-height: 60px;
          padding: 0 8px;
          border: @border;
        }

        &-textarea {
          resize: none;
          outline: none;
          height: 100%;
          width: 100%;
          font-weight: bold;
          line-height: 60px;
          overflow: hidden;
          font-size: 20px;
          padding-right: 30px;
          text-align: right;
          float: left;
          border: 1px solid @primary1-color;
        }
      }
    }
  }
}

.edit-icon {
  position: absolute;
  right: 3px;
  margin-top: -4px;
  top: 30px;
  bottom: 0;
  height: 24px;
  line-height: 24px;
  width: 23px;
  font-size: 16px;
  text-align: center;
  cursor: pointer;
  user-select: none;
  z-index: 1;
  background: white;
}

.calculator {
  z-index: 9999;
  position: absolute;
  --button-width: 50px;
  --button-height: 50px;

  display: grid;
  grid-template-areas:
	"result result result result"
	"ac plus-minus percent divide"
	"number-7 number-8 number-9 multiply"
	"number-4 number-5 number-6 subtract"
	"number-1 number-2 number-3 add"
	"number-0 dot equal equal"
	"canceld canceld enterd enterd";

  grid-template-columns: repeat(4, var(--button-width));
  grid-template-rows: repeat(6, var(--button-height));

  box-shadow: -8px -8px 16px -10px rgba(255, 255, 255, 1),
  8px 8px 16px -10px rgba(0, 0, 0, 0.15);
  padding: 1px 8px;
  width: 220px;
  height: 350px;
  border: 1px solid @green-color;
  background-color: #fafafa;
}

.calculator button {
  margin: 5px;
  padding: 0;
  border: 0;
  display: block;
  outline: none;
  border-radius: calc(var(--button-height) / 2);
  font-size: 18px;
  font-family: Helvetica;
  color: #717070;
  background: linear-gradient(135deg,
  rgba(232, 230, 230, 1) 10%,
  rgba(246, 246, 246, 1) 100%);
}

.calculator button:hover {
  box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1) inset,
  4px 4px 10px -8px rgba(0, 0, 0, 0.3) inset;
}

.calculator button:active {
  box-shadow: -4px -4px 10px -8px rgba(255, 255, 255, 1) inset,
  4px 4px 10px -8px rgba(0, 0, 0, 0.3) inset;
}

.result {
  position: relative;
  text-align: right;
  line-height: var(--button-height);
  white-space: nowrap;
  color: #666;
  overflow: hidden;
}

.result-info {
  display: inline-block;
  position: absolute;
  right: 0;
  top: 5px;
  transform-origin: right bottom;
  transition: transform 200ms ease-in-out;
  font-size: 20px;
  padding-right: 5px;
}
</style>
